package jp.co.brilliantservice.app.openar.util;

import jp.co.brilliantservice.app.openar.data.ARObject;
import jp.co.brilliantservice.app.openar.data.ScreenItem;
import jp.co.brilliantservice.utility.SdLog;

import java.util.ArrayList;
import java.util.List;
import android.location.Location;

public class Calculate {
	private static int mViewWidth;
//	private static int mViewHeight;
	private static int mRange;
	private static double mLatitude;
	private static double mLongitude;

	private static final double FORDEGREE = (180.0f / Math.PI);
	private static final double FORRADIAN = (Math.PI / 180.0f);
	private static final float CAMERA_AZIMUTH = 45.0f;
//	private static final int[] BasePosYList = {170, 150, 135, 120, 110, 80, 70, 60, 50, 40, 30};
	private static final int[] BasePosYList = {170, 140, 120, 110, 105};
	private static final float[] EPSILONS = {0.05f, 0.052f, 0.054f, 0.056f, 0.058f, 0.060f, 0.062f, 0.064f, 0.066f, 0.068f, 0.070F};

	static public void updateScreenPoints(List<ARObject> items, double pitch, double azimuth) {
		double itemAzimuth;
		double posX = 0, posY = 0;
		double angle = 0;
		double angleRadian = 0;
		if (items==null) {
			return;
		}
		synchronized (items) {
			for (int x = 0; x < items.size(); x++) {
				ARObject item = items.get(x);
				itemAzimuth = item.mAzimuth;
				if (item.mDistance>mRange) {
					// Ignore this case.
					item.setDisplay(ScreenItem.OUT);
					continue;
				}

				/********************************************************************
				* The angle from the direction of the finder to the one of the item.
				********************************************************************/
				angle = itemAzimuth - azimuth;

				/********************************************************
				* The range of the angle is: -360.0 < angle < 360.0.
				*
				* Itmes we can see are in range of
				* -360.0 < angle <= -360.0 + CAMERA_AZIMUTH, or,
				* -CAMERA_AZIMUTH <= angle <= CAMERA_AZIMUTH, or,
				* 360.0 - CAMERA_AZIMUTH <= angle < 360.0.
				* Otherwise out of range.
				********************************************************/
				if ((-360.0 < angle) && (angle <= (CAMERA_AZIMUTH - 360.0))){
					angle = angle + 360.0;
				}else if ((-CAMERA_AZIMUTH <= angle) && (angle <= CAMERA_AZIMUTH)){
//					angle = angle;
				}else if (((360.0 - CAMERA_AZIMUTH) <= angle) && (angle < 360.0)){
					angle = angle - 360.0;
				}else{
					// Ignore this case.
					item.setDisplay(ScreenItem.OUT);
					continue;
				}
				/*************************************
				* The (x,y)-coordinates on the display.
				*************************************/
				angleRadian = angle * FORRADIAN;
				posX = EPSILONS[item.mDistanceLevel] * Math.tan(angleRadian);
				posX = posX * 100 * 72;
				posX = mViewWidth/2 + posX;
				posY = BasePosYList[item.mDistanceLevel];
//					posY = mViewHeight - mViewHeight * 0.6 - mViewHeight / 60 / (item.mDistanceLevel+1);
				posY = posY - item.mCoefficient * pitch;
				item.mX = (int)posX;
				item.mY = (int)posY;
				item.setDisplay(ScreenItem.DISPLAY);
			}
		}
	}

	static private double getDistance(double lat1, double lon1, double lat2, double lon2) {
		double retDistance = 0;
		Location a = new Location("manual");
		a.setLatitude(lat1);
		a.setLongitude(lon1);
		Location b = new Location("manual");
		b.setLatitude(lat2);
		b.setLongitude(lon2);
		retDistance = a.distanceTo(b);
		return retDistance;
	}

	static public void setLocation(List<ARObject> items, double latitude, double longitude) {
		mLatitude = latitude;
		mLongitude = longitude;
		SdLog.put("latitude="+mLatitude+" longitude"+mLongitude);
		if (items==null) {
			return;
		}
		synchronized (items) {
			for (ARObject item : items) {
				item.mDistance = getDistance(mLatitude, mLongitude, item.mObj.mLatitude, item.mObj.mLongitude);
				item.mDistanceX = getDistance(mLatitude, mLongitude, mLatitude, item.mObj.mLongitude);
				item.mDistanceY = getDistance(mLatitude, mLongitude, item.mObj.mLatitude, mLongitude);
				item.mAzimuth = Math.atan(item.mDistanceY / item.mDistanceX) * FORDEGREE;
				if ((item.mObj.mLongitude - mLongitude) >= 0.0) {
					if ((item.mObj.mLatitude - mLatitude ) >= 0.0) {
						item.mAzimuth = 90.0 - item.mAzimuth;
					} else {
						item.mAzimuth = 90.0 + item.mAzimuth;
					}
				} else {
					if ((item.mObj.mLatitude - mLatitude) >= 0.0) {
						item.mAzimuth = 270.0 + item.mAzimuth;
					} else {
						item.mAzimuth = 270.0 - item.mAzimuth;
					}
				}
//				SdLog.put("item.mDistance="+item.mDistance+" mRange="+mRange);
				item.mDistanceLevel = (int)((item.mDistance / mRange) * 100) / 20;
				if (item.mDistanceLevel>5) {
					item.mDistanceLevel = 5;
				}
				item.mCoefficient = 6 - (6/5*item.mDistanceLevel);
//				SdLog.put("level="+item.mDistanceLevel+" item.mCoefficient="+item.mCoefficient);
			}
		}
    }

	static public void setLocation(ARObject item, double latitude, double longitude) {
		mLatitude = latitude;
		mLongitude = longitude;
		if (item==null) {
			return;
		}
		List<ARObject> list = new ArrayList<ARObject>();
		list.add(item);
		setLocation(list, latitude, longitude);
		list.clear();
    }

	static public void setRange(List<ARObject> items, int range) {
		mRange = range;
    	setLocation(items, mLatitude, mLongitude);
	}

    static public void setLocation(List<ARObject> items, Location location) {
    	setLocation(items, location.getLatitude(), location.getLongitude());
    }

    static public void setViewSize(int width, int height) {
//        mViewHeight = height;
        mViewWidth = width;
    }
}
